Load data

# Sourcing External R Script
source("https://raw.githubusercontent.com/Cassava2050/PPD/main/utilities_tidy.R")

# Setting Up File Paths and Parameters
folder <- here::here("data//")  
file <- "phenotype.csv"
skip_col <- 3 
trial_interest <- "MDEPR"
year_interest <- 2022

# Loading Data
# The function 'read_cassavabase' should be defined in the sourced script
sel_data <- read_cassavabase(phenotypeFile = paste0(folder, file))
## 
## Trials interested are:
##  202301DMEPR_tani 202307DMF1C_tani 202304DMPYT_dona 2023111DMF1C_dona 2023112DMF1C_tani 2023113DMEPR_dona 2023114DMEPR_tani

Standardizing Column Names

The function ‘change_colname’ should also be defined in the sourced script

sel_data_kp <- change_colname(sel_data, NA)
## [1] "Good, the column names are standardized names now!"

Changing Column type

obs_col <- c(
  names(sel_data_kp)[str_detect(names(sel_data_kp), "obs_")],
  "use_rep_number", "blockNumber",
  "use_plot_number", "use_plot_width",
  "use_plot_length"
)

mutate all traits into numeric

sel_data_kp <- sel_data_kp %>% 
  mutate(across(all_of(obs_col), as.numeric))


# remove - , replace by _
names(sel_data_kp) = gsub("-", "_", names(sel_data_kp))

# remove trials: 202301, 202304, 202307. These were analyzed 
sel_data_kp <- 
  sel_data_kp %>% filter(!str_detect(use_trial_name, "202301|202304|202307"))


# Duplications in row and cols
duplicated_plot <- row_col_dup(sel_data_kp)
## [1] "Good, there is no duplicated combination of row and column."

Plot trial layout

trial_layout(sel_data_kp)

Check the clone name

cloneName_new_old <- check_clone_name(
  clone_list = sel_data_kp$use_accession_name,
  new_names = NA,
  add_check = NULL
)
## Released varieties: [1] "Algodona"      "Bellotti"      "Brasilera"     "Caiseli"      
##  [5] "Cantaclar04"   "Cantaclar05"   "Caribena"      "Caselli"      
##  [9] "Catumare"      "CC4-Guyana"    "CC5-Guyana"    "CG1141-1"     
## [13] "CG489-31"      "CM3306-19"     "CM3306-4"      "CM3555-6"     
## [17] "CM4843-1"      "CM4919-1"      "CM523-7"       "CM6119-5"     
## [21] "CM6438-14"     "CM6740-7"      "CM6754-8"      "CM9021-2"     
## [25] "CMB8523"       "COL1438"       "COL1522"       "COL2215"      
## [29] "COL2737"       "Colombiana"    "Costena"       "Cubana"       
## [33] "Enana"         "Enanita"       "Gines"         "GM273-57"     
## [37] "GM4034-1"      "HMC-1"         "HMC1"          "HMC1P12"      
## [41] "INTA_amarilla" "KM94"          "KU50"          "Llenerita"    
## [45] "Melua31"       "NAT31"         "Negrita"       "Orense"       
## [49] "Reina"         "Reina_wx"      "Rojita"        "Romelia"      
## [53] "Ropain"        "SGB765-2"      "SGB765-4"      "Sinuana"      
## [57] "SM1127-8"      "SM1411-5"      "SM2775-4"      "SM2792-31"    
## [61] "SMB2446-2"     "Sucrena"       "TAI"           "TAI8"         
## [65] "Venezolana"    "Vergara"       "Veronica"     
## The other known clones: [1] "13SA05"     "Azulita"    "BB1"        "BB2"        "BB3"       
##  [6] "BK"         "C19"        "C243"       "C33"        "C39"       
## [11] "C4"         "C413"       "Chirosa"    "Chocoana"   "CMB8527"   
## [16] "CR52A2"     "CR52A4"     "CR60B10"    "FalsaReina" "FALSAREINA"
## [21] "HB60"       "HLS15"      "IBA920057"  "IBA972205"  "IBA980505" 
## [26] "KM140"      "KM419"      "KM505"      "KM94"       "KU50"      
## [31] "MBUNDUMALI" "N30"        "P13"        "Rayong11"   "SAUTI"     
## [36] "TME287"     "TME3"       "TMEB419"    "UNKNOWN1"   "UNKOWN2"   
## [1] "Good, the released names were correctly used"
## [1] "Now the standard names are used. Here are the released varieties"
## [1] "KU50_is_KM94"
## [1] "The check or released clones are:"
##        newName
## 1 KU50_is_KM94
trial_standard <- sel_data_kp %>%
  left_join(cloneName_new_old,
            by = c("use_accession_name" = "accession_name_ori")
  ) %>%
  select(-use_accession_name) %>%
  rename(use_accession_name = use_accession_name.y)

Add GIS data

trial_standard <- add_GIS(trial_standard)
## [1] "The locations are:"
## [1] "Dong Nai" "Tay Ninh"
## [1] "All locations are in the database."
# Get world map data for reference
vietnam_map <- map_data("world", region = "Vietnam")

# Create a data frame with your locations
locations <- data.frame(
  Location = c("Tay Ninh", "Dong Nai"),
  Latitude = c(11.3009, 11.1432),
  Longitude = c(106.1107, 107.2742)
)

# Create a ggplot object for the map
static_map <- ggplot() +
  geom_polygon(data = vietnam_map, aes(x = long, y = lat, group = group), 
               fill = "lightgray", col = "black", linewidth = 0.03) +
  geom_point(data = locations, aes(x = Longitude, y = Latitude), size = 2, color = "red") +
  geom_text_repel(data = locations, aes(x = Longitude, y = Latitude, label = Location), 
                  size = 3) +
  geom_text(aes(x = 108.5, y = 10, label = "Author: Luis Fdo. Delgado"), size = 1.5) +
  labs(x =  "Latitude", y = "Longitude") +
  labs(title = "Locations in Vietnam", subtitle = "Tay Ninh and Dong Nai") +
  theme(plot.title = element_text(face = "bold.italic"),
        plot.subtitle = element_text(face = "italic")) +
  coord_fixed(1.3) # This sets the aspect ratio

# Display the map
print(static_map)

ggsave(paste("images\\map", trial_interest, ".png", sep = "_"),
       plot = static_map, units = "in", dpi = 300, width = 6, height = 5
)

Extracting checks

accession_rep_ct <- trial_standard %>%
  count(use_trial_name, use_accession_name, use_rep_number)  %>%
  arrange(use_trial_name) %>%
  filter(n>1)
print(accession_rep_ct) 
## [1] use_trial_name     use_accession_name use_rep_number     n                 
## <0 rows> (or 0-length row.names)

Harvesting time

conducted_trials <- 
  trial_standard %>% group_by(use_trial_name, use_plant_date,use_harvest_date, use_location) %>% 
  summarise(n_gen = n_distinct(use_accession_name)) %>% 
  mutate(harvesting_time = 
           interval(ymd(use_plant_date), ymd(use_harvest_date)) %>% as.period,
         harvesting_time = paste0(harvesting_time@month, "month ", harvesting_time@day, "day")) %>% 
  ungroup()
## `summarise()` has grouped output by 'use_trial_name', 'use_plant_date',
## 'use_harvest_date'. You can override using the `.groups` argument.
print(conducted_trials %>% rmarkdown::paged_table())
##      use_trial_name use_plant_date use_harvest_date use_location n_gen
## 1 2023111DMF1C_dona  2023-March-02 2023-December-08     Dong Nai   324
## 2 2023112DMF1C_tani  2023-March-09 2023-December-08     Tay Ninh   218
## 3 2023113DMEPR_dona  2023-March-02 2023-December-07     Dong Nai    36
## 4 2023114DMEPR_tani  2023-March-09 2023-December-08     Tay Ninh    36
##   harvesting_time
## 1     9month 6day
## 2    8month 29day
## 3     9month 5day
## 4    8month 29day

plot plant number

plants_plot <- trial_standard %>%
  group_by(use_trial_name) %>%
  count(obs_planted_number_plot) 
print(plants_plot)
## # A tibble: 4 × 3
## # Groups:   use_trial_name [4]
##   use_trial_name    obs_planted_number_plot     n
##   <chr>                               <dbl> <int>
## 1 2023111DMF1C_dona                       4   648
## 2 2023112DMF1C_tani                       4   432
## 3 2023113DMEPR_dona                      10   108
## 4 2023114DMEPR_tani                      10   108

Frequency harvest plant number

plants_harvested <- trial_standard %>%
  group_by(use_trial_name) %>%
  count(obs_harvest_number) %>% arrange(desc(obs_harvest_number))

# planted and harvested
plants_plot %>% select(-n) %>% 
  left_join(plants_harvested %>% 
              summarise(harvested_plants = max(obs_harvest_number)), by = "use_trial_name") %>% 
  write.table("clipboard", sep="\t", col.names = T, row.names = F)

Double check yield calculation

plants_to_harvest <- plants_harvested %>% 
  ggplot(aes(x = factor(obs_harvest_number), 
             y = n, fill = factor(obs_harvest_number))) +
  geom_col(col = 'black') +
  #scale_fill_jco() +
  #theme_xiaofei() +
  theme(axis.text.x = element_text(vjust = 1, angle = 65),
        text = element_text(size = 20),
        legend.position="top")+
  labs(x = "Harvest_plant_number", y = "Freq", fill = "Harvest_plant_number") +
  facet_wrap(~ use_trial_name)

print(plants_to_harvest)

ggsave(paste("images\\bar", trial_interest, ".png", sep = "_"),
       plot = plants_to_harvest, units = "in", dpi = 300, width = 9, height = 6)

Compute germination, yield, yield_starch

trial_standard <- trial_standard %>%
  mutate(obs_harvest_number_plan =
           case_when(str_detect(use_trial_name, "2023111")  ~ 4,
                     str_detect(use_trial_name, "2023112")  ~ 4,
                     str_detect(use_trial_name, "2023113")  ~ 10,
                     str_detect(use_trial_name, "2023114")  ~ 10),
         obs_germination_perc = obs_germinated_number_plot/obs_planted_number_plot * 100,
         # 2) calculate area per plant
         area_plant = (use_plot_length*use_plot_width)/obs_planted_number_plot,
         # 3) calculate the yield_v4 obs_planted_number_plot
         obs_yield_ha = ifelse(obs_yield_ha == 0, NA, obs_yield_ha),
         obs_starch_content = ifelse(obs_starch_content == 0, NA, obs_starch_content),
         obs_yield_ha_v2 = (((obs_root_weight_plot*10000)/(area_plant*obs_harvest_number_plan))/1000),
         obs_starch_yield_ha = obs_starch_content * obs_yield_ha_v2 / 100)

library(plotly)
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
p1 <- trial_standard %>% ggplot() +
  geom_point(aes(x = obs_yield_ha, y = obs_yield_ha_v2, color = use_plot_number), show.legend = F) +
  facet_wrap(~use_trial_name) +
  theme_xiaofei()

ggplotly(p1)
detach("package:plotly", unload = TRUE)
LS0tDQp0aXRsZTogIlRpZHkgZGF0YSB1cCINCmF1dGhvcjogIkx1aXMgRmVybmFuZG8gRGVsZ2FkbyINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiBwYXBlcg0KICAgIGRmX3ByaW50OiB0aWJibGUNCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmZpZy5kaW0gPSBjKDcsIDQpDQpsaWJyYXJ5KGdncmVwZWwpDQpgYGANCg0KIyBMb2FkIGRhdGENCmBgYHtyfQ0KIyBTb3VyY2luZyBFeHRlcm5hbCBSIFNjcmlwdA0Kc291cmNlKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vQ2Fzc2F2YTIwNTAvUFBEL21haW4vdXRpbGl0aWVzX3RpZHkuUiIpDQoNCiMgU2V0dGluZyBVcCBGaWxlIFBhdGhzIGFuZCBQYXJhbWV0ZXJzDQpmb2xkZXIgPC0gaGVyZTo6aGVyZSgiZGF0YS8vIikgIA0KZmlsZSA8LSAicGhlbm90eXBlLmNzdiINCnNraXBfY29sIDwtIDMgDQp0cmlhbF9pbnRlcmVzdCA8LSAiTURFUFIiDQp5ZWFyX2ludGVyZXN0IDwtIDIwMjINCg0KIyBMb2FkaW5nIERhdGENCiMgVGhlIGZ1bmN0aW9uICdyZWFkX2Nhc3NhdmFiYXNlJyBzaG91bGQgYmUgZGVmaW5lZCBpbiB0aGUgc291cmNlZCBzY3JpcHQNCnNlbF9kYXRhIDwtIHJlYWRfY2Fzc2F2YWJhc2UocGhlbm90eXBlRmlsZSA9IHBhc3RlMChmb2xkZXIsIGZpbGUpKQ0KYGBgDQoNCiMgU3RhbmRhcmRpemluZyBDb2x1bW4gTmFtZXMNClRoZSBmdW5jdGlvbiAnY2hhbmdlX2NvbG5hbWUnIHNob3VsZCBhbHNvIGJlIGRlZmluZWQgaW4gdGhlIHNvdXJjZWQgc2NyaXB0DQoNCmBgYHtyfQ0Kc2VsX2RhdGFfa3AgPC0gY2hhbmdlX2NvbG5hbWUoc2VsX2RhdGEsIE5BKQ0KYGBgDQojIENoYW5naW5nIENvbHVtbiB0eXBlDQoNCmBgYHtyfQ0Kb2JzX2NvbCA8LSBjKA0KICBuYW1lcyhzZWxfZGF0YV9rcClbc3RyX2RldGVjdChuYW1lcyhzZWxfZGF0YV9rcCksICJvYnNfIildLA0KICAidXNlX3JlcF9udW1iZXIiLCAiYmxvY2tOdW1iZXIiLA0KICAidXNlX3Bsb3RfbnVtYmVyIiwgInVzZV9wbG90X3dpZHRoIiwNCiAgInVzZV9wbG90X2xlbmd0aCINCikNCmBgYA0KDQojIG11dGF0ZSBhbGwgdHJhaXRzIGludG8gbnVtZXJpYw0KDQpgYGB7cn0NCnNlbF9kYXRhX2twIDwtIHNlbF9kYXRhX2twICU+JSANCiAgbXV0YXRlKGFjcm9zcyhhbGxfb2Yob2JzX2NvbCksIGFzLm51bWVyaWMpKQ0KDQoNCiMgcmVtb3ZlIC0gLCByZXBsYWNlIGJ5IF8NCm5hbWVzKHNlbF9kYXRhX2twKSA9IGdzdWIoIi0iLCAiXyIsIG5hbWVzKHNlbF9kYXRhX2twKSkNCg0KIyByZW1vdmUgdHJpYWxzOiAyMDIzMDEsIDIwMjMwNCwgMjAyMzA3LiBUaGVzZSB3ZXJlIGFuYWx5emVkIA0Kc2VsX2RhdGFfa3AgPC0gDQogIHNlbF9kYXRhX2twICU+JSBmaWx0ZXIoIXN0cl9kZXRlY3QodXNlX3RyaWFsX25hbWUsICIyMDIzMDF8MjAyMzA0fDIwMjMwNyIpKQ0KDQoNCiMgRHVwbGljYXRpb25zIGluIHJvdyBhbmQgY29scw0KZHVwbGljYXRlZF9wbG90IDwtIHJvd19jb2xfZHVwKHNlbF9kYXRhX2twKQ0KYGBgDQojIFBsb3QgdHJpYWwgbGF5b3V0DQpgYGB7cn0NCnRyaWFsX2xheW91dChzZWxfZGF0YV9rcCkNCmBgYA0KDQojIENoZWNrIHRoZSBjbG9uZSBuYW1lDQoNCmBgYHtyfQ0KY2xvbmVOYW1lX25ld19vbGQgPC0gY2hlY2tfY2xvbmVfbmFtZSgNCiAgY2xvbmVfbGlzdCA9IHNlbF9kYXRhX2twJHVzZV9hY2Nlc3Npb25fbmFtZSwNCiAgbmV3X25hbWVzID0gTkEsDQogIGFkZF9jaGVjayA9IE5VTEwNCikNCg0KdHJpYWxfc3RhbmRhcmQgPC0gc2VsX2RhdGFfa3AgJT4lDQogIGxlZnRfam9pbihjbG9uZU5hbWVfbmV3X29sZCwNCiAgICAgICAgICAgIGJ5ID0gYygidXNlX2FjY2Vzc2lvbl9uYW1lIiA9ICJhY2Nlc3Npb25fbmFtZV9vcmkiKQ0KICApICU+JQ0KICBzZWxlY3QoLXVzZV9hY2Nlc3Npb25fbmFtZSkgJT4lDQogIHJlbmFtZSh1c2VfYWNjZXNzaW9uX25hbWUgPSB1c2VfYWNjZXNzaW9uX25hbWUueSkNCmBgYA0KIyBBZGQgR0lTIGRhdGENCg0KYGBge3J9DQp0cmlhbF9zdGFuZGFyZCA8LSBhZGRfR0lTKHRyaWFsX3N0YW5kYXJkKQ0KDQojIEdldCB3b3JsZCBtYXAgZGF0YSBmb3IgcmVmZXJlbmNlDQp2aWV0bmFtX21hcCA8LSBtYXBfZGF0YSgid29ybGQiLCByZWdpb24gPSAiVmlldG5hbSIpDQoNCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSB3aXRoIHlvdXIgbG9jYXRpb25zDQpsb2NhdGlvbnMgPC0gZGF0YS5mcmFtZSgNCiAgTG9jYXRpb24gPSBjKCJUYXkgTmluaCIsICJEb25nIE5haSIpLA0KICBMYXRpdHVkZSA9IGMoMTEuMzAwOSwgMTEuMTQzMiksDQogIExvbmdpdHVkZSA9IGMoMTA2LjExMDcsIDEwNy4yNzQyKQ0KKQ0KDQojIENyZWF0ZSBhIGdncGxvdCBvYmplY3QgZm9yIHRoZSBtYXANCnN0YXRpY19tYXAgPC0gZ2dwbG90KCkgKw0KICBnZW9tX3BvbHlnb24oZGF0YSA9IHZpZXRuYW1fbWFwLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCANCiAgICAgICAgICAgICAgIGZpbGwgPSAibGlnaHRncmF5IiwgY29sID0gImJsYWNrIiwgbGluZXdpZHRoID0gMC4wMykgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBsb2NhdGlvbnMsIGFlcyh4ID0gTG9uZ2l0dWRlLCB5ID0gTGF0aXR1ZGUpLCBzaXplID0gMiwgY29sb3IgPSAicmVkIikgKw0KICBnZW9tX3RleHRfcmVwZWwoZGF0YSA9IGxvY2F0aW9ucywgYWVzKHggPSBMb25naXR1ZGUsIHkgPSBMYXRpdHVkZSwgbGFiZWwgPSBMb2NhdGlvbiksIA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDMpICsNCiAgZ2VvbV90ZXh0KGFlcyh4ID0gMTA4LjUsIHkgPSAxMCwgbGFiZWwgPSAiQXV0aG9yOiBMdWlzIEZkby4gRGVsZ2FkbyIpLCBzaXplID0gMS41KSArDQogIGxhYnMoeCA9ICAiTGF0aXR1ZGUiLCB5ID0gIkxvbmdpdHVkZSIpICsNCiAgbGFicyh0aXRsZSA9ICJMb2NhdGlvbnMgaW4gVmlldG5hbSIsIHN1YnRpdGxlID0gIlRheSBOaW5oIGFuZCBEb25nIE5haSIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQuaXRhbGljIiksDQogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJpdGFsaWMiKSkgKw0KICBjb29yZF9maXhlZCgxLjMpICMgVGhpcyBzZXRzIHRoZSBhc3BlY3QgcmF0aW8NCg0KIyBEaXNwbGF5IHRoZSBtYXANCnByaW50KHN0YXRpY19tYXApDQoNCmdnc2F2ZShwYXN0ZSgiaW1hZ2VzXFxtYXAiLCB0cmlhbF9pbnRlcmVzdCwgIi5wbmciLCBzZXAgPSAiXyIpLA0KICAgICAgIHBsb3QgPSBzdGF0aWNfbWFwLCB1bml0cyA9ICJpbiIsIGRwaSA9IDMwMCwgd2lkdGggPSA2LCBoZWlnaHQgPSA1DQopDQoNCmBgYA0KIyBFeHRyYWN0aW5nIGNoZWNrcw0KDQpgYGB7ciBtYXgucHJpbnQ9MX0NCmFjY2Vzc2lvbl9yZXBfY3QgPC0gdHJpYWxfc3RhbmRhcmQgJT4lDQogIGNvdW50KHVzZV90cmlhbF9uYW1lLCB1c2VfYWNjZXNzaW9uX25hbWUsIHVzZV9yZXBfbnVtYmVyKSAgJT4lDQogIGFycmFuZ2UodXNlX3RyaWFsX25hbWUpICU+JQ0KICBmaWx0ZXIobj4xKQ0KcHJpbnQoYWNjZXNzaW9uX3JlcF9jdCkgDQpgYGANCg0KIyBIYXJ2ZXN0aW5nIHRpbWUNCg0KYGBge3IgbWF4LnByaW50PTF9DQpjb25kdWN0ZWRfdHJpYWxzIDwtIA0KICB0cmlhbF9zdGFuZGFyZCAlPiUgZ3JvdXBfYnkodXNlX3RyaWFsX25hbWUsIHVzZV9wbGFudF9kYXRlLHVzZV9oYXJ2ZXN0X2RhdGUsIHVzZV9sb2NhdGlvbikgJT4lIA0KICBzdW1tYXJpc2Uobl9nZW4gPSBuX2Rpc3RpbmN0KHVzZV9hY2Nlc3Npb25fbmFtZSkpICU+JSANCiAgbXV0YXRlKGhhcnZlc3RpbmdfdGltZSA9IA0KICAgICAgICAgICBpbnRlcnZhbCh5bWQodXNlX3BsYW50X2RhdGUpLCB5bWQodXNlX2hhcnZlc3RfZGF0ZSkpICU+JSBhcy5wZXJpb2QsDQogICAgICAgICBoYXJ2ZXN0aW5nX3RpbWUgPSBwYXN0ZTAoaGFydmVzdGluZ190aW1lQG1vbnRoLCAibW9udGggIiwgaGFydmVzdGluZ190aW1lQGRheSwgImRheSIpKSAlPiUgDQogIHVuZ3JvdXAoKQ0KDQpwcmludChjb25kdWN0ZWRfdHJpYWxzICU+JSBybWFya2Rvd246OnBhZ2VkX3RhYmxlKCkpDQpgYGANCiMgcGxvdCBwbGFudCBudW1iZXINCg0KYGBge3IgbWF4LnByaW50PTF9DQpwbGFudHNfcGxvdCA8LSB0cmlhbF9zdGFuZGFyZCAlPiUNCiAgZ3JvdXBfYnkodXNlX3RyaWFsX25hbWUpICU+JQ0KICBjb3VudChvYnNfcGxhbnRlZF9udW1iZXJfcGxvdCkgDQpwcmludChwbGFudHNfcGxvdCkNCmBgYA0KDQojIEZyZXF1ZW5jeSBoYXJ2ZXN0IHBsYW50IG51bWJlcg0KDQpgYGB7cn0NCnBsYW50c19oYXJ2ZXN0ZWQgPC0gdHJpYWxfc3RhbmRhcmQgJT4lDQogIGdyb3VwX2J5KHVzZV90cmlhbF9uYW1lKSAlPiUNCiAgY291bnQob2JzX2hhcnZlc3RfbnVtYmVyKSAlPiUgYXJyYW5nZShkZXNjKG9ic19oYXJ2ZXN0X251bWJlcikpDQoNCiMgcGxhbnRlZCBhbmQgaGFydmVzdGVkDQpwbGFudHNfcGxvdCAlPiUgc2VsZWN0KC1uKSAlPiUgDQogIGxlZnRfam9pbihwbGFudHNfaGFydmVzdGVkICU+JSANCiAgICAgICAgICAgICAgc3VtbWFyaXNlKGhhcnZlc3RlZF9wbGFudHMgPSBtYXgob2JzX2hhcnZlc3RfbnVtYmVyKSksIGJ5ID0gInVzZV90cmlhbF9uYW1lIikgJT4lIA0KICB3cml0ZS50YWJsZSgiY2xpcGJvYXJkIiwgc2VwPSJcdCIsIGNvbC5uYW1lcyA9IFQsIHJvdy5uYW1lcyA9IEYpDQpgYGANCg0KIyBEb3VibGUgY2hlY2sgeWllbGQgY2FsY3VsYXRpb24NCg0KYGBge3IgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9OH0NCnBsYW50c190b19oYXJ2ZXN0IDwtIHBsYW50c19oYXJ2ZXN0ZWQgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBmYWN0b3Iob2JzX2hhcnZlc3RfbnVtYmVyKSwgDQogICAgICAgICAgICAgeSA9IG4sIGZpbGwgPSBmYWN0b3Iob2JzX2hhcnZlc3RfbnVtYmVyKSkpICsNCiAgZ2VvbV9jb2woY29sID0gJ2JsYWNrJykgKw0KICAjc2NhbGVfZmlsbF9qY28oKSArDQogICN0aGVtZV94aWFvZmVpKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dCh2anVzdCA9IDEsIGFuZ2xlID0gNjUpLA0KICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbj0idG9wIikrDQogIGxhYnMoeCA9ICJIYXJ2ZXN0X3BsYW50X251bWJlciIsIHkgPSAiRnJlcSIsIGZpbGwgPSAiSGFydmVzdF9wbGFudF9udW1iZXIiKSArDQogIGZhY2V0X3dyYXAofiB1c2VfdHJpYWxfbmFtZSkNCg0KcHJpbnQocGxhbnRzX3RvX2hhcnZlc3QpDQoNCmdnc2F2ZShwYXN0ZSgiaW1hZ2VzXFxiYXIiLCB0cmlhbF9pbnRlcmVzdCwgIi5wbmciLCBzZXAgPSAiXyIpLA0KICAgICAgIHBsb3QgPSBwbGFudHNfdG9faGFydmVzdCwgdW5pdHMgPSAiaW4iLCBkcGkgPSAzMDAsIHdpZHRoID0gOSwgaGVpZ2h0ID0gNikNCmBgYA0KDQojIENvbXB1dGUgZ2VybWluYXRpb24sIHlpZWxkLCB5aWVsZF9zdGFyY2gNCg0KYGBge3J9DQp0cmlhbF9zdGFuZGFyZCA8LSB0cmlhbF9zdGFuZGFyZCAlPiUNCiAgbXV0YXRlKG9ic19oYXJ2ZXN0X251bWJlcl9wbGFuID0NCiAgICAgICAgICAgY2FzZV93aGVuKHN0cl9kZXRlY3QodXNlX3RyaWFsX25hbWUsICIyMDIzMTExIikgIH4gNCwNCiAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QodXNlX3RyaWFsX25hbWUsICIyMDIzMTEyIikgIH4gNCwNCiAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QodXNlX3RyaWFsX25hbWUsICIyMDIzMTEzIikgIH4gMTAsDQogICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KHVzZV90cmlhbF9uYW1lLCAiMjAyMzExNCIpICB+IDEwKSwNCiAgICAgICAgIG9ic19nZXJtaW5hdGlvbl9wZXJjID0gb2JzX2dlcm1pbmF0ZWRfbnVtYmVyX3Bsb3Qvb2JzX3BsYW50ZWRfbnVtYmVyX3Bsb3QgKiAxMDAsDQogICAgICAgICAjIDIpIGNhbGN1bGF0ZSBhcmVhIHBlciBwbGFudA0KICAgICAgICAgYXJlYV9wbGFudCA9ICh1c2VfcGxvdF9sZW5ndGgqdXNlX3Bsb3Rfd2lkdGgpL29ic19wbGFudGVkX251bWJlcl9wbG90LA0KICAgICAgICAgIyAzKSBjYWxjdWxhdGUgdGhlIHlpZWxkX3Y0IG9ic19wbGFudGVkX251bWJlcl9wbG90DQogICAgICAgICBvYnNfeWllbGRfaGEgPSBpZmVsc2Uob2JzX3lpZWxkX2hhID09IDAsIE5BLCBvYnNfeWllbGRfaGEpLA0KICAgICAgICAgb2JzX3N0YXJjaF9jb250ZW50ID0gaWZlbHNlKG9ic19zdGFyY2hfY29udGVudCA9PSAwLCBOQSwgb2JzX3N0YXJjaF9jb250ZW50KSwNCiAgICAgICAgIG9ic195aWVsZF9oYV92MiA9ICgoKG9ic19yb290X3dlaWdodF9wbG90KjEwMDAwKS8oYXJlYV9wbGFudCpvYnNfaGFydmVzdF9udW1iZXJfcGxhbikpLzEwMDApLA0KICAgICAgICAgb2JzX3N0YXJjaF95aWVsZF9oYSA9IG9ic19zdGFyY2hfY29udGVudCAqIG9ic195aWVsZF9oYV92MiAvIDEwMCkNCg0KbGlicmFyeShwbG90bHkpDQoNCnAxIDwtIHRyaWFsX3N0YW5kYXJkICU+JSBnZ3Bsb3QoKSArDQogIGdlb21fcG9pbnQoYWVzKHggPSBvYnNfeWllbGRfaGEsIHkgPSBvYnNfeWllbGRfaGFfdjIsIGNvbG9yID0gdXNlX3Bsb3RfbnVtYmVyKSwgc2hvdy5sZWdlbmQgPSBGKSArDQogIGZhY2V0X3dyYXAofnVzZV90cmlhbF9uYW1lKSArDQogIHRoZW1lX3hpYW9mZWkoKQ0KDQpnZ3Bsb3RseShwMSkNCmRldGFjaCgicGFja2FnZTpwbG90bHkiLCB1bmxvYWQgPSBUUlVFKQ0KYGBgDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0K